package cn.itcast.netty.c3;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringEncoder;

import java.net.InetSocketAddress;

public class EventLoopClient {
    public static void main(String[] args) throws InterruptedException {
        // 1. 启动类
        Channel channel = new Bootstrap()
                // 2. 添加 EventLoop  其实这个我们客户端可以不用但是这里现在先统一
                .group(new NioEventLoopGroup())
                // 3. 选择客户端 channel 实现
                .channel(NioSocketChannel.class)
                // 4. 添加处理器
                .handler(new ChannelInitializer<NioSocketChannel>() {
                    @Override // 在与服务器端连接建立后被调用做初始化工作
                    protected void initChannel(NioSocketChannel ch) throws Exception {
                        //pipeline翻译过来就是流水线的意思 其实这里面就是一个责任链模式
                        //一个处理器处理完就交给下一个处理器去处理，直到所有处理器都处理完
                        //handler可以对数据或者啥的进行处理 处理器分为inbound(入站) 和 outbound(出站)
                        //数据输入时由inbound(入站)处理器来处理 数据输出就由outbound(出站)处理器来处理
                        //这里是个编码的handler 因为服务端是把字节转换成字符串读取，所以我们这边就得把要发的数据转换成字节然后发送
                        ch.pipeline().addLast(new StringEncoder());
                    }
                })
                // 5. 连接到服务器
                .connect(new InetSocketAddress("localhost", 8080))
                // 这是个阻塞方法，只有在连接建立完成后才会往下运行
                // 也可以通过addListener()这个方法 来代替sync()方法来处理
                // addListener()就是异步多一个线程去处理 里面会让你实现一个处理类里面写具体的操作逻辑即可 这样主线程直接走了无所谓因为又是另外的线程了
                .sync()
                .channel(); //拿到channel对象 这里的channel对象自然就是服务器与客户端之间的channel对象了
                System.out.println(channel);
                //我们debug卡住后 用idea的调试方式evalute expression来写channel.writeAndFlush()写数据
                //我们会发现我们多调用几次多发送几次数据线程名称都是一样的
                //因为一个线程跟eventLoop绑定后以后每次这个线程的操作都是这个eventLoop在调度不会被其他的eventLoop干预
                //我们启动多几个客户端发送就能看出区别了
                //但是一个eventLoop是可以管理多个客户端的,例如服务器端只设置了2个线程 那么就是这两个线程(eventLoop)来管理所有的客户端线程(多个selector多路复用)
                //记得把dubug的all方式改成Thread方式  all就是运行到这行代码后所有线程都卡住 thread就是只卡住当前线程其他线程不影响
                //因为这边是多线程运行的 读写都是eventLoop即另外的线程在处理所以不能用ALL不然一直看不出效果
                System.out.println("");
    }
}
